package wish.filters;

import java.util.ArrayList;
import java.util.List;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Text;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.SimpleNodeIterator;

import wish.model.Record;


public class ScoreFunctionFilter {

	private long byChar;
	private long byImage; //15
	private long byParent; //150
	private long byBreak; //50
	private long byFactor; //5
	private NodeFilter separatorsFilter = new OrFilter(new TagNameFilter("br"), new TagNameFilter("hr"));
	private NodeFilter imagesFilter = new NodeClassFilter(ImageTag.class);
	private NodeFilter textFilter = new NodeClassFilter(Text.class);
	

	public ScoreFunctionFilter(long byChar, long byImage, long byParent, long byBreak, long byFactor){
		
		this.byChar = byChar;
		this.byImage = byImage;
		this.byParent = byParent;
		this.byBreak = byBreak;
		this.byFactor = byFactor;
	
	}
	
	public long getScore(Record record){
		
		int a = getNumberOfParents(record);
		
		long b = getTotalTextLenght(record);
		
		int c = getNumberOfImages(record);
		
		int d = getNumberOfSeparatortags(record);
		
		return (a * byParent) + ((b*byChar + (c * byImage) + d*byBreak) * byFactor);
		
	}

	private int getNumberOfSeparatortags(Record record) {
		
		NodeList nl = record.getNodeList().extractAllNodesThatMatch(separatorsFilter ,true);
		
		return nl.size();
	}

	private int getNumberOfImages(Record record) {
		NodeList nl = record.getNodeList().extractAllNodesThatMatch(imagesFilter  ,true);
		
		return nl.size();
	}

	private long getTotalTextLenght(Record record) {
		
		NodeList nl = record.getNodeList().extractAllNodesThatMatch(textFilter  ,true);
		
		SimpleNodeIterator texts = nl.elements();
		
		long ret = 0;
		
		while (texts.hasMoreNodes()){
			
			ret += getTextLenght(texts.nextNode().getText().trim().toCharArray());
			
		}

		return ret;
	}

	private long getTextLenght(char[] characters) {
		
		long ret = 0;
		
		for (int i = 0; i < characters.length; i++) {
			
			if (Character.isLetterOrDigit(characters[i]))
				ret++;
			
		}
		
		return ret;
	}

	private int getNumberOfParents(Record record) {
		return record.getLevel()-1;
	}
	
}
